# /usr/bin/python3
# coding=utf-8

import sys

sys.path.append("..")
sys.path.append(".")
sys.dont_write_bytecode = True


class JsonResponseValidator:
    """
    JSON响应断言类
    功能：
    1. 检查JSON中是否存在指定key
    2. 检查指定key的值是否符合预期
    3. 支持嵌套JSON结构和数组遍历
    """

    def __init__(self, response_json):
        """
        初始化断言类
        :param response_json: 要验证的JSON数据(dict/list)
        """
        self.response = response_json
        self.last_key = None
        self.last_values = []

    def key_exists(self, key):
        """
        断言指定的key存在于JSON中
        :param key: 要查找的键名
        :return: self (支持链式调用)
        """
        self.last_key = key
        self.last_values = self._find_values(self.response, key)
        assert self.last_values, f"断言失败: JSON中未找到键 '{key}'"
        return self

    def value_equals(self, expected_value):
        """
        断言找到的key的值等于预期值
        :param expected_value: 预期值
        :return: self (支持链式调用)
        """
        assert self.last_key is not None, "必须先调用key_exists()方法"
        assert expected_value in self.last_values, (
            f"断言失败: 键 '{self.last_key}' 的值不等于预期值\n"
            f"预期: {expected_value}\n"
            f"实际找到的值: {self.last_values}"
        )
        return self

    def value_contains(self, expected_part):
        """
        断言找到的key的值包含预期字符串(部分匹配)
        :param expected_part: 预期包含的字符串
        :return: self (支持链式调用)
        """
        assert self.last_key is not None, "必须先调用key_exists()方法"
        found = any(str(expected_part) in str(val) for val in self.last_values)
        assert found, (
            f"断言失败: 键 '{self.last_key}' 的值不包含预期内容\n"
            f"预期包含: {expected_part}\n"
            f"实际找到的值: {self.last_values}"
        )
        return self

    def value_not_contains(self, unexpected_part):
        """
        断言所有找到的值不包含指定内容
        """
        assert self.last_key is not None, "必须先调用key_exists()方法"
        invalid = [v for v in self.last_values if str(unexpected_part) in str(v)]
        assert not invalid, f"值不应包含{unexpected_part}，但发现{len(invalid)}个违规值"
        return self

    def value_not_null(self):
        """
        断言找到的key的值不为空
        :return: self (支持链式调用)
        """
        assert self.last_key is not None, "必须先调用key_exists()方法"
        null_values = [val for val in self.last_values if val in (None, "", [], {})]
        assert not null_values, (
            f"断言失败: 键 '{self.last_key}' 存在空值\n"
            f"找到的空值数量: {len(null_values)}/{len(self.last_values)}\n"
            f"所有空值: {null_values}"
        )
        return self

    def value_is_null(self):
        """
        断言找到的key的值为空
        :return: self (支持链式调用)
        """
        assert self.last_key is not None, "必须先调用key_exists()方法"
        invalid_values = [val for val in self.last_values if val not in (None, "", [], {})]
        assert not invalid_values, (
            f"断言失败: 键 '{self.last_key}' 存在非空值\n"
            f"找到的非空值数量: {len(invalid_values)}/{len(self.last_values)}\n"
            f"所有非空值: {invalid_values}"
        )
        return self

    def value_is_true(self):
        """
        断言所有找到的值为True（严格校验布尔类型）
        """
        assert self.last_key is not None, "必须先调用key_exists()方法"
        invalid = [v for v in self.last_values if not isinstance(v, bool) or v != True]
        assert not invalid, f"值应全为True，但发现{len(invalid)}个非True值"
        return self

    def value_is_false(self):
        """
        断言所有找到的值为False（严格校验布尔类型）
        """
        assert self.last_key is not None, "必须先调用key_exists()方法"
        invalid = [v for v in self.last_values if not isinstance(v, bool) or v != False]
        assert not invalid, f"值应全为False，但发现{len(invalid)}个非False值"
        return self

    def value_greater_than(self, ref_value):
        """
        断言找到的key的值大于
        :return: self (支持链式调用)
        """
        assert self.last_key is not None, "必须先调用key_exists()方法"
        # 找出所有不大于参考值的无效值
        invalid_values = [val for val in self.last_values if val <= ref_value]
        # 如果存在无效值则断言失败
        assert not invalid_values, (
            f"断言失败: 键 '{self.last_key}' 存在不大于 {ref_value} 的值\n"
            f"不符合数量: {len(invalid_values)}/{len(self.last_values)}\n"
            f"无效值列表: {invalid_values}"
        )
        return self

    def value_less_than(self, ref_value):
        """
        断言找到的key的值小于指定参考值
        :param ref_value: 要比较的参考值(所有找到的值必须小于该值)
        :return: self (支持链式调用)
        """
        assert self.last_key is not None, "必须先调用key_exists()方法"
        # 找出所有不小于参考值的无效值
        invalid_values = [val for val in self.last_values if val >= ref_value]
        # 如果存在无效值则断言失败
        assert not invalid_values, (
            f"断言失败: 键 '{self.last_key}' 存在不小于 {ref_value} 的值\n"
            f"不符合数量: {len(invalid_values)}/{len(self.last_values)}\n"
            f"无效值列表: {invalid_values}"
        )
        return self

    def _find_values(self, data, search_key):
        """
        递归查找JSON中所有匹配的键值
        :param data: 要搜索的数据(dict/list)
        :param search_key: 要查找的键
        :return: 找到的值列表
        """
        results = []

        if isinstance(data, dict):
            for key, value in data.items():
                if key == search_key:
                    results.append(value)
                # 递归搜索嵌套结构
                if isinstance(value, (dict, list)):
                    results.extend(self._find_values(value, search_key))

        elif isinstance(data, list):
            for item in data:
                if isinstance(item, (dict, list)):
                    results.extend(self._find_values(item, search_key))

        return results

    def get_first_value(self):
        """
        获取找到的第一个值
        :return: 第一个匹配的值
        """
        assert self.last_values, "没有找到任何值"
        self.last_values = [self.last_values[0]]
        return self

    def get_all_values(self):
        """
        获取找到的所有值
        :return: 所有匹配的值列表
        """
        return self.last_values